import {ObjectID} from "mongodb";
import  {Promise} from 'es6-promise';
import {Request, Response} from "express";

import PWSApp from "../../core/app";
import HomeBaseAction from "./act.base";
import {Magics} from "../../core/magics";
import {ModList} from "../../core/types";
import * as utils from '../../core/utils';
import UserModel from "../../models/mod.user";
import {ErrCode} from "../../core/error.code";
import {MongoColls} from "../../config/mongo";
import CartModel from "../../models/mod.cart";
import FavoriteModel from "../../models/mod.favorite";
import {
    RouteType ,
} from "../../core/defines";
import ProductModel, {
    ProductStatus,
    ProductInfo,
    SearchOpt,
} from "../../models/mod.product";

declare function require(name: string): any;

export default class ProductAction extends HomeBaseAction {
    private _cartMod: CartModel;
    private _userMod: UserModel;
    private _productMod: ProductModel;
    private _favoriteMod: FavoriteModel;

    constructor(app: PWSApp){
        super(app);
        this._cartMod = new CartModel( this.db.collection(MongoColls.CART) );
        this._userMod = new UserModel( this.db.collection(MongoColls.USER) );
        this._productMod = new ProductModel(this.db.collection(MongoColls.PRODUCT));
        this._favoriteMod = new FavoriteModel( this.db.collection(MongoColls.FAVORITE) );
    }

    name() { return `${this.app.name}Product`; }

    protected _setRoutes() {
        this._setRoot('/api/product');

        this._route(RouteType.GET, '/search', this._actSearchProd);
        this._route(RouteType.GET, '/:id', this._actGetProdById);
    }

    private _actSearchProd(req: Request, res: Response){
        Promise.resolve().then(() => {
            let {key, cate, sub_cate, limit, sort, page} = req.query;
            // if (!key && !cate && !sub_cate) {
            //     return Promise.reject({err_code: ErrCode.ArgsMissing});
            // }
            req.query.page = utils.isNumeric(page) ? utils.toInt(page) : 0;
            req.query.limit = utils.isNumber(limit) ? utils.toInt(limit) : Magics.HomePageItemCount;
            return this._productMod.search(<SearchOpt>req.query);
        }).then( (data: ModList) => {
            let {records, curr_page, total_count, total_page} = data;
            let result = {
                curr_page, total_count, total_page,
                prods: records,
                err_code: ErrCode.Success,
            };
            res.send(result);
        }).catch( (err) => {
            this._errHandler(req, res, err);
        });
    }

    private _actGetProdById(req: Request, res: Response){
        let prodTemp: Object;
        let {id} = req.params;
        Promise.resolve().then( () => {
            if(!utils.isObjectId(id)){
                return Promise.reject({err_code: ErrCode.ArgsInvalid});
            }
            let filter = {
                _id: utils.toObjectId(id),
                status: ProductStatus.PUBLISHED
            };
            return this._productMod.checkExist(filter);
        }).then( (product: ProductInfo) => {
            if (!product) {
                return Promise.reject({err_code: ErrCode.ProdNotFound});
            }
            prodTemp = product;
            let sessUser = req.session[Magics.SessUser] || {};
            if(sessUser['_id']){
                let userId: ObjectID = utils.toObjectId(sessUser['_id']);
                let filter = {
                    user_id: userId,
                    src_id: utils.toObjectId(id)
                };
                return Promise.all([
                    this._cartMod.getCartCount({user_id: userId}),
                    this._favoriteMod.checkExist(filter)
                ]);
            }
            return [];
        }).then((ret) => {
            let cartCount = ret[0] || 0;
            let is_favor = !!ret[1];
            let result = {
                product: prodTemp,
                is_favorite: is_favor,
                cart_count: cartCount,
                err_code: ErrCode.Success
            };
            res.send(result);
        }).catch( (err) => {
            this._errHandler(req, res, err);
        })
    }

}
